using iTextSharp.text.pdf;
using PrintTool.Models;
using System.Drawing.Printing;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace PrintTool.Services;

public class PdfService
{
    // Windows API声明
    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);

    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    [DllImport("user32.dll")]
    private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool OpenPrinter(string szPrinter, out IntPtr hPrinter, IntPtr pd);

    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool ClosePrinter(IntPtr hPrinter);

    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool StartDocPrinter(IntPtr hPrinter, int Level, ref DOCINFO_1 di1);

    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool EndDocPrinter(IntPtr hPrinter);

    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool StartPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool EndPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);

    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool GetPrinter(IntPtr hPrinter, int dwLevel, IntPtr pPrinter, int dwBuf, out int dwNeeded);

    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool SetPrinter(IntPtr hPrinter, int dwLevel, IntPtr pPrinter, int dwCommand);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private struct DOCINFO_1
    {
        [MarshalAs(UnmanagedType.LPStr)]
        public string pDocName;
        [MarshalAs(UnmanagedType.LPStr)]
        public string pOutputFile;
        [MarshalAs(UnmanagedType.LPStr)]
        public string pDatatype;
    }

    private const int SW_HIDE = 0;
    private const int SW_SHOW = 5;

    public static List<string> GetAvailablePrinters()
    {
        var printers = new List<string>();
        foreach (string printer in PrinterSettings.InstalledPrinters)
        {
            printers.Add(printer);
        }
        return printers;
    }

    public static bool IsPrinterAvailable(string printerName)
    {
        try
        {
            var settings = new PrinterSettings { PrinterName = printerName };
            return settings.IsValid;
        }
        catch
        {
            return false;
        }
    }

    public static string GetPrinterStatus(string printerName)
    {
        try
        {
            var settings = new PrinterSettings { PrinterName = printerName };
            if (!settings.IsValid)
            {
                return "不可用";
            }

            // 检查打印机状态
            if (settings.IsDefaultPrinter)
            {
                return "默认打印机";
            }
            else
            {
                return "可用";
            }
        }
        catch
        {
            return "状态未知";
        }
    }

    public static int GetPdfPageCount(string filePath)
    {
        try
        {
            using var reader = new PdfReader(filePath);
            return reader.NumberOfPages;
        }
        catch
        {
            return 0;
        }
    }

    public static bool IsValidPdfFile(string filePath)
    {
        try
        {
            using var reader = new PdfReader(filePath);
            return reader.NumberOfPages > 0;
        }
        catch
        {
            return false;
        }
    }

    public static async Task<bool> PrintPdfAsync(PdfFile pdfFile)
    {
        try
        {
            return await Task.Run(() => PrintPdfDirectly(pdfFile));
        }
        catch (Exception ex)
        {
            MessageBox.Show($"打印失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }
    }

    private static bool PrintPdfDirectly(PdfFile pdfFile)
    {
        try
        {
            // 检查打印机是否可用
            if (!IsPrinterAvailable(pdfFile.SelectedPrinter))
            {
                MessageBox.Show($"打印机 '{pdfFile.SelectedPrinter}' 不可用", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            // 在打印前设置打印机颜色属性
            SetPrinterColorSettings(pdfFile.SelectedPrinter, pdfFile.IsColorPrint);

            // 方法1：尝试使用Windows打印服务进行静默打印
            if (TryPrintWithWindowsSpooler(pdfFile))
            {
                return true;
            }

            // 方法2：尝试使用Ghostscript进行静默打印（如果可用）
            if (TryPrintWithGhostscript(pdfFile))
            {
                return true;
            }

            // 方法3：使用Adobe Reader进行静默打印
            string adobeReaderPath = GetAdobeReaderPath();
            if (!string.IsNullOrEmpty(adobeReaderPath))
            {
                return PrintWithAdobeReader(pdfFile, adobeReaderPath);
            }
            else
            {
                // 方法4：备用方案：使用Windows ShellExecute进行静默打印
                return PrintWithShellExecute(pdfFile);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show($"PDF打印失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }
    }

    private static bool TryPrintWithWindowsSpooler(PdfFile pdfFile)
    {
        try
        {
            // 如果设置了副本数量，需要多次打印
            for (int copy = 0; copy < pdfFile.PrintCopies; copy++)
            {
                // 使用Windows打印服务直接发送打印任务
                var startInfo = new ProcessStartInfo
                {
                    FileName = "cmd.exe",
                    Arguments = $"/c copy \"{pdfFile.FilePath}\" \"{pdfFile.SelectedPrinter}\"",
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    WindowStyle = ProcessWindowStyle.Hidden
                };

                using var process = Process.Start(startInfo);
                if (process != null)
                {
                    process.WaitForExit();
                    if (process.ExitCode != 0)
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }

                Thread.Sleep(1000);
            }
            return true;
        }
        catch
        {
            return false;
        }
    }

    private static bool TryPrintWithGhostscript(PdfFile pdfFile)
    {
        try
        {
            // 查找Ghostscript安装路径
            string gsPath = GetGhostscriptPath();
            if (string.IsNullOrEmpty(gsPath))
            {
                return false;
            }

            // 如果设置了副本数量，需要多次打印
            for (int copy = 0; copy < pdfFile.PrintCopies; copy++)
            {
                // 构建Ghostscript命令参数，包含颜色设置
                string colorArg = pdfFile.IsColorPrint ? "" : "-sProcessColorModel=DeviceGray";
                var startInfo = new ProcessStartInfo
                {
                    FileName = gsPath,
                    Arguments = $"-dNOPAUSE -dBATCH -dPrinted {colorArg} -sDEVICE=mswinpr2 -sOutputFile=\"%printer%{pdfFile.SelectedPrinter}\" \"{pdfFile.FilePath}\"",
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    WindowStyle = ProcessWindowStyle.Hidden
                };

                using var process = Process.Start(startInfo);
                if (process != null)
                {
                    process.WaitForExit();
                    if (process.ExitCode != 0)
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
        catch
        {
            return false;
        }
    }

    private static string GetGhostscriptPath()
    {
        // 常见的Ghostscript安装路径
        string[] possiblePaths = {
            @"C:\Program Files\gs\gs10.01.1\bin\gswin64c.exe",
            @"C:\Program Files\gs\gs10.00.0\bin\gswin64c.exe",
            @"C:\Program Files\gs\gs9.56.1\bin\gswin64c.exe",
            @"C:\Program Files\gs\gs9.54.0\bin\gswin64c.exe",
            @"C:\Program Files (x86)\gs\gs10.01.1\bin\gswin32c.exe",
            @"C:\Program Files (x86)\gs\gs10.00.0\bin\gswin32c.exe",
            @"C:\Program Files (x86)\gs\gs9.56.1\bin\gswin32c.exe",
            @"C:\Program Files (x86)\gs\gs9.54.0\bin\gswin32c.exe"
        };

        foreach (string path in possiblePaths)
        {
            if (File.Exists(path))
            {
                return path;
            }
        }

        // 尝试从PATH环境变量中查找
        try
        {
            var startInfo = new ProcessStartInfo
            {
                FileName = "where",
                Arguments = "gswin64c",
                UseShellExecute = false,
                RedirectStandardOutput = true,
                CreateNoWindow = true
            };

            using var process = Process.Start(startInfo);
            if (process != null)
            {
                string output = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
                if (process.ExitCode == 0 && !string.IsNullOrEmpty(output))
                {
                    string[] lines = output.Split('\n');
                    if (lines.Length > 0)
                    {
                        string path = lines[0].Trim();
                        if (File.Exists(path))
                        {
                            return path;
                        }
                    }
                }
            }
        }
        catch
        {
            // 忽略错误
        }

        return string.Empty;
    }

    private static bool PrintWithAdobeReader(PdfFile pdfFile, string adobeReaderPath)
    {
        try
        {
            // 如果设置了副本数量，需要多次打印
            for (int copy = 0; copy < pdfFile.PrintCopies; copy++)
            {
                // 构建Adobe Reader命令参数，包含颜色设置
                string colorArg = pdfFile.IsColorPrint ? "" : "/g"; // /g参数表示灰度打印（黑白）
                var startInfo = new ProcessStartInfo
                {
                    FileName = adobeReaderPath,
                    Arguments = $"/t {colorArg} \"{pdfFile.FilePath}\" \"{pdfFile.SelectedPrinter}\"",
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    WindowStyle = ProcessWindowStyle.Hidden
                };

                using var process = Process.Start(startInfo);
                if (process != null)
                {
                    process.WaitForExit();
                    if (process.ExitCode != 0)
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
        catch
        {
            return false;
        }
    }

    private static bool PrintWithShellExecute(PdfFile pdfFile)
    {
        try
        {
            // 如果设置了副本数量，需要多次打印
            for (int copy = 0; copy < pdfFile.PrintCopies; copy++)
            {
                // 方法1：尝试使用Windows print命令进行静默打印
                if (TryPrintWithWindowsPrint(pdfFile))
                {
                    Thread.Sleep(1000);
                    continue;
                }

                // 方法2：尝试使用rundll32进行静默打印
                if (TryPrintWithRundll32(pdfFile))
                {
                    Thread.Sleep(1000);
                    continue;
                }

                // 方法3：尝试使用默认应用程序
                if (!TryPrintWithDefaultApp(pdfFile))
                {
                    return false;
                }

                Thread.Sleep(1000);
            }
            return true;
        }
        catch
        {
            return false;
        }
    }

    private static bool TryPrintWithWindowsPrint(PdfFile pdfFile)
    {
        try
        {
            // 使用Windows的printui.dll进行静默打印
            var startInfo = new ProcessStartInfo
            {
                FileName = "rundll32.exe",
                Arguments = $"printui.dll,PrintUIEntry /k /n \"{pdfFile.SelectedPrinter}\" \"{pdfFile.FilePath}\"",
                UseShellExecute = false,
                CreateNoWindow = true,
                WindowStyle = ProcessWindowStyle.Hidden
            };

            using var process = Process.Start(startInfo);
            if (process != null)
            {
                process.WaitForExit();
                return process.ExitCode == 0;
            }
            return false;
        }
        catch
        {
            return false;
        }
    }

    private static bool TryPrintWithRundll32(PdfFile pdfFile)
    {
        try
        {
            var startInfo = new ProcessStartInfo
            {
                FileName = "rundll32.exe",
                Arguments = $"shell32.dll,ShellExec_RunDLL \"{pdfFile.FilePath}\" /t",
                UseShellExecute = false,
                CreateNoWindow = true,
                WindowStyle = ProcessWindowStyle.Hidden
            };

            using var process = Process.Start(startInfo);
            if (process != null)
            {
                process.WaitForExit();
                return process.ExitCode == 0;
            }
            return false;
        }
        catch
        {
            return false;
        }
    }

    private static bool TryPrintWithDefaultApp(PdfFile pdfFile)
    {
        try
        {
            // 方法2：使用默认应用程序的静默打印
            var startInfo = new ProcessStartInfo
            {
                FileName = pdfFile.FilePath,
                Verb = "print",
                UseShellExecute = true,
                CreateNoWindow = true,
                WindowStyle = ProcessWindowStyle.Hidden
            };

            using var process = Process.Start(startInfo);
            if (process != null)
            {
                process.WaitForExit();
                return process.ExitCode == 0;
            }
            return false;
        }
        catch
        {
            return false;
        }
    }

    private static bool SetPrinterColorSettings(string printerName, bool isColorPrint)
    {
        try
        {
            // 方法1：尝试使用注册表设置打印机颜色属性
            SetPrinterColorViaRegistry(printerName, isColorPrint);

            // 方法2：使用Windows打印API设置打印机颜色属性
            var settings = new PrinterSettings { PrinterName = printerName };
            if (!settings.IsValid)
            {
                return false;
            }

            // 尝试设置颜色模式
            if (settings.CanDuplex)
            {
                // 如果打印机支持双面打印，通常也支持颜色设置
                // 这里可以添加更多的打印机属性设置
                return true;
            }

            return true;
        }
        catch
        {
            return false;
        }
    }

    private static bool SetPrinterColorViaRegistry(string printerName, bool isColorPrint)
    {
        try
        {
            // 使用注册表设置打印机颜色属性
            string colorMode = isColorPrint ? "1" : "0";
            var startInfo = new ProcessStartInfo
            {
                FileName = "reg.exe",
                Arguments = $"add \"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\\{printerName}\" /v ColorMode /t REG_DWORD /d {colorMode} /f",
                UseShellExecute = false,
                CreateNoWindow = true,
                WindowStyle = ProcessWindowStyle.Hidden
            };

            using var process = Process.Start(startInfo);
            if (process != null)
            {
                process.WaitForExit();
                return process.ExitCode == 0;
            }
            return false;
        }
        catch
        {
            return false;
        }
    }



    private static string GetAdobeReaderPath()
    {
        // 常见的Adobe Reader安装路径
        string[] possiblePaths = {
            @"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe",
            @"C:\Program Files\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe",
            @"C:\Program Files (x86)\Adobe\Reader\AcroRd32.exe",
            @"C:\Program Files\Adobe\Reader\AcroRd32.exe"
        };

        foreach (string path in possiblePaths)
        {
            if (File.Exists(path))
            {
                return path;
            }
        }

        return string.Empty;
    }



    public static async Task<bool> PrintMultiplePdfsAsync(List<PdfFile> pdfFiles, IProgress<int>? progress = null)
    {
        int totalFiles = pdfFiles.Count;
        int processedFiles = 0;

        foreach (var pdfFile in pdfFiles)
        {
            if (!pdfFile.IsSelected) continue;

            bool success = await PrintPdfAsync(pdfFile);
            if (!success)
            {
                return false;
            }

            processedFiles++;
            progress?.Report((int)((double)processedFiles / totalFiles * 100));
        }

        return true;
    }
} 